package com.pulse.common.utils.sor;

import com.pulse.common.utils.sor.domain.Block;
import com.pulse.common.utils.sor.domain.Blocks;
import com.pulse.common.utils.sor.domain.SorInfo;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

public class Parts {
    public static final double Sol = 299792.458 / 1.0e6;  // = 0.299792458 km/usec

    /**
     * 从输入流中读取字符串（以 null 结尾）
     *
     * @param fh 输入流
     * @return 解码后的字符串
     * @throws IOException 如果读取失败
     */
    public static String getString(InputStream fh) throws IOException {
        List<Byte> byteList = new ArrayList<>();
        int currentByte;

        // 读取字节，直到遇到 null字符（0x00）
        while ((currentByte = fh.read()) != 0x00 && currentByte != -1) {
            byteList.add((byte) currentByte);
        }

        // 将字节数组解码为 UTF-8 字符串
        byte[] byteArray = new byte[byteList.size()];
        for (int i = 0; i < byteList.size(); i++) {
            byteArray[i] = byteList.get(i);
        }
        return new String(byteArray, "UTF-8");
    }

    /**
     * 从输入流中读取无符号整数（小端序）
     *
     * @param fh    输入流
     * @param size  字节数（2、4 或 8）
     * @return 解析后的无符号整数
     * @throws IOException 如果读取失败
     */
    public static long getUInt(InputStream fh, int size) throws IOException {
        byte[] buffer = new byte[size];
        int bytesRead = fh.read(buffer);

        if (bytesRead != size) {
            throw new IOException("意外的文件结尾");
        }

        // 使用 ByteBuffer 处理小端序
        ByteBuffer bb = ByteBuffer.wrap(buffer);
        bb.order(ByteOrder.LITTLE_ENDIAN);

        switch (size) {
            case 2:
                return bb.getShort() & 0xFFFFL;  // 2 字节，转换为无符号 short
            case 4:
                return bb.getInt() & 0xFFFFFFFFL;  // 4 字节，转换为无符号 int
            case 8:
                return bb.getLong();  // 8 字节，直接返回 long
            default:
                throw new IllegalArgumentException("无效字节数：" + size);
        }
    }

    /**
     * 从输入流中读取有符号整数（小端序）
     *
     * @param fh     输入流
     * @param nbytes 字节数（2、4 或 8）
     * @return 解析后的有符号整数
     * @throws IOException 如果读取失败
     */
    public static long getSigned(InputStream fh, int nbytes) throws IOException {
        byte[] buffer = new byte[nbytes];
        int bytesRead = fh.read(buffer);

        if (bytesRead != nbytes) {
            throw new IOException("意外的文件结尾");
        }

        // 使用 ByteBuffer 处理小端序
        ByteBuffer bb = ByteBuffer.wrap(buffer);
        bb.order(ByteOrder.LITTLE_ENDIAN);

        switch (nbytes) {
            case 2:
                return bb.getShort();  // 2 字节，short
            case 4:
                return bb.getInt();  // 4 字节，int
            case 8:
                return bb.getLong();  // 8 字节，long
            default:
                throw new IllegalArgumentException("无效字节数：" + nbytes);
        }
    }

    /**
     * 读取指定数量的字节并将其格式化为十六进制字符串
     *
     * @param fh     输入流
     * @param nbytes 字节数（默认为 1）
     * @return 十六进制字符串
     * @throws IOException 如果读取失败
     */
    public static String getHex(InputStream fh, int nbytes) throws IOException {
        StringBuilder hexString = new StringBuilder();

        for (int i = 0; i < nbytes; i++) {
            int b = fh.read();  // 读取一个字节
            if (b == -1) {
                throw new IOException("意外的文件结尾");
            }
            hexString.append(String.format("%02X ", b));  // 格式化为两位十六进制并添加空格
        }

        return hexString.toString().trim();  // 去除末尾多余的空格
    }

    /**
     * 读取指定块的内容而不进行处理
     *
     * @param fh      输入流
     * @param bname   块名称
     * @param sorInfo 存储结果的对象
     * @return 状态字符串
     */
    public static String slurp(BufferedInputStream fh, String bname, SorInfo sorInfo) {
        String status = "nok";

        try {
            // 获取块的引用
            List<Block> klist = new ArrayList<>();
            klist.add(sorInfo.getBlocks().getGenParams());
            klist.add(sorInfo.getBlocks().getSupParams());
            klist.add(sorInfo.getBlocks().getFxdParams());
            klist.add(sorInfo.getBlocks().getKeyEvents());
            klist.add(sorInfo.getBlocks().getDataPts());
            klist.add(sorInfo.getBlocks().getCksum());
            for (Block other : sorInfo.getBlocks().getOthers()) {
                klist.add(other);
            }

            Optional<Block> first = klist.stream()
                    .filter(block -> bname.equals(block.getName()))
                    .findFirst();

            Block refBlock = first.get();

            long startpos = (long) refBlock.getPos();
            int nn = refBlock.getSize();

            // 跳过块的起始位置
            fh.reset();
            fh.skip(startpos);

            // 读取块的内容
            byte[] buffer = new byte[nn];
            fh.read(buffer);

            status = "ok";
        } catch (IOException e) {
            e.printStackTrace();
        }

        return status;
    }
}
